﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Ue.CQRS.Repositories
{
    public interface IRepository<TKey, TValue>
    {
        TValue this[TKey key] { get; set; }

        ICollection<TKey> Keys { get; }

        ICollection<TValue> Values { get; }

        TValue GetOrAdd(TKey key, Func<TKey, TValue> addEntityFactory);

        TValue AddOrUpdate(TKey key, Func<TKey, TValue> addEntityFactory, Func<TKey, TValue, TValue> updateEntityFactory);

        TValue Remove(TKey key);

        bool ContainsKey(TKey key);

        IEnumerable<TValue> FindBy(Expression<Func<TValue, bool>> predicate, int? skip, int? count);
    }

    public static class IRepositoryExtensions
    {
        public static TValue GetOrAdd<TKey, TValue>(this IRepository<TKey, TValue> repository,TKey key, TValue entity)
        {
            return repository.GetOrAdd(key, k => entity);
        }

        public static TValue AddOrUpdate<TKey, TValue>(this IRepository<TKey, TValue> repository, TKey key, TValue entity)
        {
            return repository.AddOrUpdate(key, k => entity, (k, v) => entity);
        }

        public static TValue AddOrUpdate<TKey, TValue>(this IRepository<TKey, TValue> repository, TKey key, Func<TKey, TValue> entityFactory)
        {
            return repository.AddOrUpdate(key, entityFactory, (k, v) => entityFactory(k));
        }

        public static IEnumerable<TValue> FindBy<TKey, TValue>(this IRepository<TKey, TValue> repository, Expression<Func<TValue, bool>> predicate)
        {
            return repository.FindBy(predicate, null, null);
        }

    }
}